
package xj.graph2d.app;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.filechooser.FileFilter;

import xj.graph2d.Document;
import xj.graph2d.DocumentException;
import xj.graph2d.DrawAttr;
import xj.graph2d.Encoder;
import xj.graph2d.FontMap;
import xj.graph2d.SimpleDrawView;
import xj.graph2d.UndoManager;
import xj.graph2d.app.project.Project;
import xj.graph2d.app.project.ProjectException;
import xj.graph2d.app.resources.Style;
import xj.util.gui.ExtensionFileFilter;

import static xj.app.BaseApplicationFrame.drawFrameIcon;
import static xj.app.BaseApplicationFrame.getResourceString;
import static xj.app.BaseApplicationFrame.getSystemProperty;
import static xj.graph2d.DocumentConstants.DEFAULT_FILE_TYPE;
import static xj.graph2d.DocumentConstants.SERIALIZATION_FILE_TYPE;
import static xj.graph2d.DocumentConstants.UNKNOWN_FILE_TYPE;
import static xj.graph2d.DocumentConstants.XML_FILE_TYPE;

// ////////////////////////////////////////////////////////
//
// Action classes
//
// ////////////////////////////////////////////////////////

class ActionHelper {} 

// Project actions

class CloseProjectListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    main.closeCurrentProject();
  }

}

class LoadProjectListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public LoadProjectListener() {
  }

  public void init() {
  }

  public void actionPerformed(ActionEvent e) {
    if (chooser == null) {
      chooser = new JFileChooser();
      chooser.addChoosableFileFilter(DrawApp.projectFileFilter);
      chooser.setCurrentDirectory(new File(main.getDefaultDir()));
      chooser.setDialogTitle(getResourceString("OpenProjectDialog.title"));
    }

    chooser.rescanCurrentDirectory();
    int retval = chooser.showOpenDialog(main.getJFrame());
    if (retval == JFileChooser.APPROVE_OPTION) {
      File theFile = chooser.getSelectedFile();
      if (theFile != null) {
	String filename = theFile.getAbsolutePath();
	if (theFile.isFile()) {
	  try {
	    main.loadProject(filename);
	  } catch (IOException ex) {
	    main.reportOpenProjectError(filename, ex.getMessage());
	  } catch (ProjectException ex) {
	    main.reportOpenProjectError(filename, ex.getMessage());
	  } catch (DocumentException ex) {
	    main.reportOpenProjectError(filename, ex.getMessage());
	  }
	} else {
	  // not a file, no such file theFile
	  String msg1 = "File not found: " + filename;
	  main.reportOpenProjectError(filename, msg1);
	}
      }
    }
  }

}

class OpenRecentProjectListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {

  }

}

class SaveProjectListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    main.saveProject();
  }

}

class SaveAsProjectListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public SaveAsProjectListener() {
  }

  public void init() {
    /*
         * if (main != null) {
         * chooser.addChoosableFileFilter(DrawApp.projectFileFilter);
         * //chooser.addChoosableFileFilter(DrawApp.defaultFileFilter);
         * 
         * chooser.setCurrentDirectory(new File(main.getDefaultDir())); }
         */
  }

  public void actionPerformed(ActionEvent e) {
    saveAs();
  }

  public void saveAs() {
    // System.out.println("SaveAsProjectListener.saveAs()");
    if (chooser == null) {
      chooser = new JFileChooser();
      chooser.addChoosableFileFilter(DrawApp.projectFileFilter);
      chooser.setCurrentDirectory(new File(main.getDefaultDir()));
      chooser.setDialogTitle(getResourceString("SaveProjectDialog.title"));
    }

    chooser.rescanCurrentDirectory();
    chooser.setSelectedFile(new File(main.normalizeFilename(main.getCurrentProjectFilename())));
    int retval = chooser.showDialog(main.getJFrame(), 
				    getResourceString("SaveAsProject.text"));
    if (retval == JFileChooser.APPROVE_OPTION) {
      File theFile = chooser.getSelectedFile();
      if (theFile != null) {
	String filename = theFile.getAbsolutePath();
	if (!theFile.isDirectory()) {
	  String ext = Project.PROJECT_FILE_SUFFIX;
	  filename = Document.setFileExtension(filename, ext);
	  main.saveProjectAs(filename);
	} else {
	  // selected a directory
	  String msg1 = filename + " is a directory";
	  JOptionPane.showMessageDialog(main.getJFrame(), msg1, 
					"Save Project Error",
					JOptionPane.ERROR_MESSAGE);	  
	}
      }
    }
  }

}

// Project Archive

class LoadProjectArchiveListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public LoadProjectArchiveListener() {
  }

  public void init() {
  }

  public void actionPerformed(ActionEvent e) {
    if (chooser == null) {
      chooser = new JFileChooser();
      chooser.addChoosableFileFilter(DrawApp.projectArchiveFileFilter);
      chooser.setCurrentDirectory(new File(main.getDefaultDir()));
      chooser.setDialogTitle(getResourceString("OpenProjectArchiveDialog.title"));
    }

    chooser.rescanCurrentDirectory();
    int retval = chooser.showOpenDialog(main.getJFrame());
    if (retval == JFileChooser.APPROVE_OPTION) {
      File theFile = chooser.getSelectedFile();
      if (theFile != null) {
	String filename = theFile.getAbsolutePath();
	if (theFile.isFile()) {
	  try {
	    main.loadProjectArchive(filename);
	  } catch (IOException ex) {
	    String msg1 = "Load project failed: " + filename;
	    String msg2 = ex.getMessage();
	    main.displayMessage(msg1);

	    //ex.printStackTrace();

	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1 + "\n" + msg2,
					  "Load Project Archive Error", 
					  JOptionPane.ERROR_MESSAGE);
	  } catch (ProjectException ex) {
	    String msg1 = "Load project failed: " + filename;
	    String msg2 = ex.getMessage();
	    main.displayMessage(msg1);

	    //ex.printStackTrace();

	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1 + "\n" + msg2,
					  "Load Project Archive Error", 
					  JOptionPane.ERROR_MESSAGE);
	  } catch (DocumentException ex) {
	    String msg1 = "Load project failed: " + filename;
	    String msg2 = ex.getMessage();
	    main.displayMessage(msg1);
	    
	    //ex.printStackTrace();

	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1 + "\n" + msg2,
					  "Load Project Archive Error", 
					  JOptionPane.ERROR_MESSAGE);
	  }
	} else {
	  // not a file, no such file theFile
	  String msg1 = "File not found: " + filename;
	  JOptionPane.showMessageDialog(main.getJFrame(), 
					msg1,
					"Load Project Archive Error", 
					JOptionPane.ERROR_MESSAGE);
	}
      }
    }
  }

}

class SaveProjectArchiveListener extends DrawAction implements ActionListener {

  public SaveProjectArchiveListener() {
  }

  public void actionPerformed(ActionEvent e) {
    main.saveProjectArchive(null);
  }

}

class SaveAsProjectArchiveListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public SaveAsProjectArchiveListener() {
  }

  public void init() {
  }

  public void actionPerformed(ActionEvent e) {
    saveArchive();
  }

  public void saveArchive() {
    if (chooser == null) {
      chooser = new JFileChooser();
      chooser.addChoosableFileFilter(DrawApp.projectArchiveFileFilter);
      chooser.setCurrentDirectory(new File(main.getDefaultDir()));
      chooser.setDialogTitle(getResourceString("SaveProjectArchiveDialog.title"));
    }

    chooser.rescanCurrentDirectory();
    // chooser.setSelectedFile(new
    // File(main.normalizeFilename(main.getCurrentProjectFilename())));
    int retval = chooser.showDialog(main.getJFrame(),  
				    getResourceString("SaveAsProjectArchive.text"));
    if (retval == JFileChooser.APPROVE_OPTION) {
      File theFile = chooser.getSelectedFile();
      if (theFile != null) {
	String filename = theFile.getAbsolutePath();
	if (!theFile.isDirectory()) {
	  String ext = Project.PROJECT_ARCHIVE_SUFFIX;
	  filename = Document.setFileExtension(filename, ext);
	  main.saveProjectArchive(filename);
	} else {
	  // selected a directory
	  String msg1 = filename + " is a directory";
	  JOptionPane.showMessageDialog(main.getJFrame(), msg1,
					"Save Project Archive Error", 
					JOptionPane.ERROR_MESSAGE);

	}
      }
    }
  }

}

// File actions

class NewFileListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    boolean doNewFile = true;
    if (main.isSingleDocumentMode()) {
      doNewFile = main.saveCurrentFileDialog("NewFileDialog");
    }
    if (doNewFile) {
      main.newFile();
    }
  }

}

class NewTabListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    main.newTab();
  }

}

class NewWindowListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {


  }

}

class CloseFileListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {

  }

}

class OpenFileListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public OpenFileListener() {
  }

  public void init() {
  }

  public void initFileChooser() {
    FileFilter[] filters = main.getSupportedFileFilters();
    if (filters != null) {
      int n = filters.length;
      for (int i = 0; i < n; i++) {
	FileFilter f = filters[i];
	if (f != null) {
	  chooser.addChoosableFileFilter(f);
	}
      }
    }
    // chooser.addChoosableFileFilter(DrawApp.defaultFileFilter);
    if (DrawApp.testing) {
      chooser.addChoosableFileFilter(DrawApp.xmlFileFilter);
      chooser.addChoosableFileFilter(DrawApp.serializationFileFilter);
    }

    chooser.setCurrentDirectory(new File(main.getDefaultDir()));
    chooser.setDialogTitle(getResourceString("OpenFileDialog.title"));
  }

  public void actionPerformed(ActionEvent e) {
    if (chooser == null) {
      chooser = new JFileChooser();
      initFileChooser();
    }

    boolean doOpenFile = true;
    if (main.isSingleDocumentMode()) {
      doOpenFile = main.saveCurrentFileDialog("OpenFileDialog");
    }
    if (doOpenFile) {
      chooser.rescanCurrentDirectory();
      // chooser.setApproveButtonMnemonic('O');
      // int retval = chooser.showDialog(null, "Open");
      int retval = chooser.showOpenDialog(null);
      if (retval == JFileChooser.APPROVE_OPTION) {
	File theFile = chooser.getSelectedFile();
	// System.out.println("OpenFileListener.actionPerformed() @1
	// file=" + theFile);
	if (theFile != null) {
	  String filename = theFile.getAbsolutePath();
	  if (theFile.isFile()) {
	    int filetype = UNKNOWN_FILE_TYPE;
	    FileFilter filter = chooser.getFileFilter();
	    if (filter instanceof ExtensionFileFilter) {
	      ExtensionFileFilter efilter = (ExtensionFileFilter) filter;
	      filetype = efilter.getFileType();
	    } else if (filter != null) {
	      String des = filter.getDescription();
	      if (DrawApp.defaultFileDescription.equals(des)) {
		filetype = DEFAULT_FILE_TYPE;
	      } else if (DrawApp.xmlFileDescription.equals(des)) {
		filetype = XML_FILE_TYPE;
	      } else if (DrawApp.serializationFileDescription.equals(des)) {
		filetype = SERIALIZATION_FILE_TYPE;
	      }
	    }

	    try {
	      main.setCurrentFilename(filename);
	      main.openFile(filename, filetype);
	    } catch (IOException ex) {
	      main.reportOpenFileError(filename, ex.getMessage());
	    } catch (DocumentException ex) {
	      main.reportOpenFileError(filename, ex.getMessage());
	    }
	  } else {
	    // not a file, no such file theFile
	    String msg1 = "File not found: " + filename;
	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1, "Open File Error",
					  JOptionPane.ERROR_MESSAGE);
	  }
	}
      }
    }
  }

}

class OpenRecentFileListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    boolean doOpenFile = true;
    if (main.isSingleDocumentMode()) {
      doOpenFile = main.saveCurrentFileDialog("OpenFileDialog");
    }
    if (doOpenFile && e != null) {
      Object src = e.getSource();
      if (src instanceof JMenuItem) {
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	// System.out.println("OpenRecentFileListener: " + cmd);
	Object o = DrawApp.recentlyOpenedFiles.get(cmd);
	if (o != null && o instanceof FileEntry) {
	  FileEntry entry = (FileEntry) o;
	  try {
	    main.setCurrentFilename(entry.filename);
	    main.openFile(entry.filename, entry.filetype);
	  } catch (IOException ex) {
	  } catch (DocumentException ex) {
	  }
	}
      }
    }
  }
}

class SaveFileListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent evt) {
    try {
      main.saveFile();
    } catch (IOException e) {
      String msg1 = "Save file error: " + main.getCurrentFilename();
      String msg2 = e.getMessage();
      main.displayMessage(msg1);
      JOptionPane.showMessageDialog(main.getJFrame(), 
				    msg1 + "\n" + msg2,
				    "Save File Error", 
				    JOptionPane.ERROR_MESSAGE);
    } catch (DocumentException e) {
      String msg1 = "Save file error: " + main.getCurrentFilename();
      String msg2 = e.getMessage();
      main.displayMessage(msg1);
      JOptionPane.showMessageDialog(main.getJFrame(), 
				    msg1 + "\n" + msg2,
				    "Save File Error", 
				    JOptionPane.ERROR_MESSAGE);
    }
  }

}

class SaveAsFileListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public SaveAsFileListener() {
  }

  public void init() {
    /*
         * if (main != null) { }
         */
  }

  public void initFileChooser() {
    FileFilter[] filters = main.getSupportedFileFilters();
    if (filters != null) {
      int n = filters.length;
      for (int i = 0; i < n; i++) {
	FileFilter f = filters[i];
	if (f != null) {
	  chooser.addChoosableFileFilter(f);
	}
      }
    }
    // chooser.addChoosableFileFilter(DrawApp.defaultFileFilter);
    if (DrawApp.testing) {
      chooser.addChoosableFileFilter(DrawApp.xmlFileFilter);
      chooser.addChoosableFileFilter(DrawApp.serializationFileFilter);
    }

    chooser.setCurrentDirectory(new File(main.getDefaultDir()));
    chooser.setDialogTitle(getResourceString("SaveFileDialog.title"));
  }

  public void actionPerformed(ActionEvent e) {
    saveAs();
  }

  public void saveAs() {
    // System.out.println("SaveAsFileListener.saveAs()");

    if (chooser == null) {
      chooser = new JFileChooser();
      initFileChooser();
    }

    chooser.rescanCurrentDirectory();
    chooser.setSelectedFile(new File(main.normalizeFilename(main.getCurrentFilename())));
    int retval = chooser.showDialog(null, getResourceString("SaveAs.text"));
    if (retval == JFileChooser.APPROVE_OPTION) {

      // System.out.println("SaveAsFileListener.saveAs() @1");

      File theFile = chooser.getSelectedFile();
      if (theFile != null) {
	String filename = theFile.getAbsolutePath();
	if (!theFile.isDirectory()) {
	  // System.out.println("SaveAsFileListener.saveAs()
	  // filename=" + filename);

	  int filetype = UNKNOWN_FILE_TYPE;
	  String ext = null;
	  FileFilter filter = chooser.getFileFilter();
	  if (filter instanceof ExtensionFileFilter) {
	    ExtensionFileFilter efilter = (ExtensionFileFilter) filter;
	    filetype = efilter.getFileType();
	    ext = efilter.getExtension();
	  } else if (filter != null) {
	    String des = filter.getDescription();
	    if (DrawApp.defaultFileDescription.equals(des)) {
	      filetype = DEFAULT_FILE_TYPE;
	    } else if (DrawApp.xmlFileDescription.equals(des)) {
	      filetype = XML_FILE_TYPE;
	    } else if (DrawApp.serializationFileDescription.equals(des)) {
	      filetype = SERIALIZATION_FILE_TYPE;
	    }
	    ext = DrawApp.getExtension(filetype);
	  }

	  filename = Document.setFileExtension(filename, ext);
	  /*
	   * String fext = null; int i = filename.lastIndexOf('.'); int j =
	   * filename.lastIndexOf(File.separator); if (i > j && i <
	   * filename.length()-1) { fext =
	   * filename.substring(i+1).toLowerCase(); } if (ext != null) {
	   * if (fext != null) { if (!ext.equals(fext)) { //filename +=
	   * ("." + ext); filename = filename.substring(0, i) + "." + ext; } }
	   * else { filename += ("." + ext); } }
	   */

	  main.setCurrentFilename(filename);
	  try {
	    main.saveFileAs(filename, filetype);
	  } catch (IOException e) {
	    String msg1 = "Save file error: " + filename;
	    String msg2 = e.getMessage();
	    main.displayMessage(msg1);
	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1 + "\n" + msg2,
					  "Save File Error", 
					  JOptionPane.ERROR_MESSAGE);
	  } catch (DocumentException e) {
	    String msg1 = "Save file error: " + filename;
	    String msg2 = e.getMessage();
	    main.displayMessage(msg1);
	    JOptionPane.showMessageDialog(main.getJFrame(), 
					  msg1 + "\n" + msg2,
					  "Save File Error", 
					  JOptionPane.ERROR_MESSAGE);
	  }
	} else {
	  // selected a directory
	  String msg1 = filename + " is a directory";
	  JOptionPane.showMessageDialog(main.getJFrame(), 
					msg1, "Save File Error",
					JOptionPane.ERROR_MESSAGE);

	}
      }
    }
  }

}

// Other actions

class ExitListener 
  extends DrawAction 
  implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    main.getApplicationFrame().exitAppFrame();
  }

}

class MenuAction extends DrawAction implements MenuListener {

  public void menuSelected(MenuEvent e) {
    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenu) {
	JMenu b = (JMenu) src;
	String cmd = b.getActionCommand();
	main.displayHelpMessage(cmd + ".message");
      }
    }
  }

  public void menuDeselected(MenuEvent e) {
    // view.displayMessage(null);
  }

  public void menuCanceled(MenuEvent e) {
    // view.displayMessage(null);
  }

}

class MenuDragAction extends DrawAction implements MenuDragMouseListener {

  public void menuDragMouseDragged(MenuDragMouseEvent e) {

  }

  public void menuDragMouseEntered(MenuDragMouseEvent e) {
    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenuItem) {
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	main.displayHelpMessage(cmd + ".message");
      }
    }
  }

  public void menuDragMouseExited(MenuDragMouseEvent e) {
    main.displayMessage(null);
  }

  public void menuDragMouseReleased(MenuDragMouseEvent e) {
    main.displayMessage(null);
  }

}

class ExportFileListener extends DrawAction implements ActionListener {

  JFileChooser chooser = null;

  public ExportFileListener() {
    // chooser.setCurrentDirectory(new File(DrawApp.defaultDir));
  }

  public void init() {
  }

  public void actionPerformed(ActionEvent e) {
    if (chooser == null) {
      chooser = new JFileChooser();
      chooser.setCurrentDirectory(new File(main.getDefaultDir()));
    }

    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenuItem) {
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	Encoder enc = main.getEncoder(cmd);

	if (DrawApp.debug) {
	  System.out.println("ExportFileListener cmd=" + cmd + 
			     " (enc != null): " + (enc != null));
	  Iterator iter = main.getAllEncoders();
	  while (iter.hasNext()) {
	    Encoder aenc = (Encoder) iter.next();
	    System.out.println("  available encoder name=" + aenc.getName());
	  }
	}

	if (enc != null) {
	  main.setEncoderView(enc);

	  FileFilter fileFilter = enc.getFileFilter();
	  chooser.addChoosableFileFilter(fileFilter);

	  String curFilename = main.getCurrentFilename();
	  if (curFilename != null) {
	    String expFilename = curFilename;
	    String ext = enc.getFileExtension();
	    // int j = curFilename.lastIndexOf(File.separator);
	    // if (j >= 0) {
	    // expFilename = curFilename.substring(j + 1);
	    // }
	    int i = expFilename.lastIndexOf(".");
	    int j = expFilename.lastIndexOf(File.separator);
	    if (i > j) {
	      expFilename = expFilename.substring(0, i);
	    }
	    expFilename += ("." + ext);

	    // System.out.println("ExportFileListener curFilename="
	    // + curFilename +
	    // " expFilename=" + expFilename);

	    chooser.setSelectedFile(new File(expFilename));
	  } else {
	    chooser.rescanCurrentDirectory();
	  }

	  int retval = chooser.showDialog(null, getResourceString("ExportTo.message") + " " + cmd);
	  if (retval == JFileChooser.APPROVE_OPTION) {
	    File theFile = chooser.getSelectedFile();
	    if (theFile != null) {
	      if (!theFile.isDirectory()) {
		String filename = chooser.getSelectedFile().getAbsolutePath();
		// setCurrentFilename(filename);
		if (DrawApp.debug) {
		  System.out.println("Export to " + cmd + " in " + filename + " [" + 
				     enc.getClass().getName() + "]");
		}
		try {
		  enc.encode(filename);
		} catch (IOException ex) {
		  // System.out.println("Unable to write file:
		  // " + filename);
		  // System.out.println(ex.getMessage());
		  // ex.printStackTrace();
		  main.displayMessage(getResourceString("WriteFileFail.message") + " " + filename);
		}
	      }
	    }
	  }
	  chooser.removeChoosableFileFilter(fileFilter);
	} else {
	  // System.out.println("Export format " + cmd + " is not
	  // supported.");
	  main.displayMessage(getResourceString("ExportFail.message") + " " + cmd);
	}
      }
    }
  }

}

class PrintListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {

    if (DrawApp.debug) {
      System.out.println("PrintListener.actionPerformed()");
    }

    if (e != null) {
      Object src = e.getSource();
      if (src != null && 
	  src instanceof AbstractButton) {
	AbstractButton b = (AbstractButton) src;
	String cmd = b.getActionCommand();

	if ("PageSetup".equals(cmd)) {

	  if (DrawApp.debug) {
	    System.out.println("Page setup");
	  }

	  main.doPageSetup();
	} else if ("PrintPreview".equals(cmd)) {
	  if (DrawApp.debug) {
	    System.out.println("Print preview");
	  }

	  main.doPrintPreview();
	} else if ("Print".equals(cmd)) {

	  if (DrawApp.debug) {
	    System.out.println("Print");
	  }

	  main.doPrint();
	}
      }
    }
  }

}

class UndoRedoListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenuItem) {
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	if ("Undo".equals(cmd)) {
	  main.undoCommand();
	} else if ("Redo".equals(cmd)) {
	  main.redoCommand();
	}
      }
    }
  }

}

class EditListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenuItem) {
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	if ("Cut".equals(cmd)) {
	  main.cut();
	} else if ("Copy".equals(cmd)) {
	  main.copy();
	} else if ("Paste".equals(cmd)) {
	  main.paste();
	}
      }
    }
  }

}

class RefreshListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    SimpleDrawView view = main.getView();
    view.refresh();
  }

}

class ZoomActionListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    if (e != null) {
      Object src = e.getSource();
      if (src != null && src instanceof JMenuItem) {
	SimpleDrawView view = main.getView();
	JMenuItem b = (JMenuItem) src;
	String cmd = b.getActionCommand();
	if ("ZoomIn".equals(cmd)) {
	  main.zoomControl.zoom(true);
	} else if ("ZoomOut".equals(cmd)) {
	  main.zoomControl.zoom(false);
	} else if ("ZoomRestore".equals(cmd)) {
	  main.zoomControl.setZoomDisplay(100);
	} else if ("ZoomFitWidth".equals(cmd)) {
	  main.zoomControl.zoomFitWidth();
	} else if ("ZoomFitHeight".equals(cmd)) {
	  main.zoomControl.zoomFitHeight();
	} else if ("ZoomFitWindow".equals(cmd)) {
	  main.zoomControl.zoomFitWindow();
	} 
	/*
	float f = view.getScaleFactor();
	if ("ZoomIn".equals(cmd)) {
	  f *= 1.5;
	} else if ("ZoomOut".equals(cmd)) {
	  f /= 1.5;
	}
	view.setScaleFactor(f);
	view.repaint();
	*/
      }
    }
  }

}

class DrawOptionListener extends DrawAction implements ActionListener {

  public void actionPerformed(ActionEvent e) {
    System.out.println("DrawOptionListener");

    SimpleDrawView view = main.getView();
    Object src = e.getSource();
    if (src instanceof JCheckBoxMenuItem) {
      JCheckBoxMenuItem cm = (JCheckBoxMenuItem) src;
      String cmd = cm.getActionCommand();
      if ("AntiAliasing".equals(cmd)) {
	view.setUseAntialias(cm.getState());
      } else if ("FractionalMetrics".equals(cmd)) {
	boolean fm = cm.getState();
	view.setFractionalMetrics(fm);
	FontMap.setFontRendingContext(fm);
      }
    } else if (src instanceof JMenuItem) {
      JMenuItem mi = (JMenuItem) src;
      String cmd = mi.getActionCommand();
      if ("SetGradientPaint".equals(cmd)) {
	System.out.println("DrawOptionListener: SetGradientPaint");
	DrawAttr attr = view.getDrawAttr();
	if (attr != null) {
	  attr.setGradientColor1(Color.lightGray);
	  attr.setGradientColor2(Color.blue);
	  attr.setGradientMode(DrawAttr.LINEAR_GRADIENT_LEFT_TO_RIGHT);
	}
      } else if ("SetGradientPaint2".equals(cmd)) {
	System.out.println("DrawOptionListener: SetGradientPaint2");
	DrawAttr attr = view.getDrawAttr();
	if (attr != null) {
	  attr.setGradientColor1(Color.lightGray);
	  attr.setGradientColor2(Color.blue);
	  attr.setGradientMode(DrawAttr.LINEAR_GRADIENT_TOP_TO_BOTTOM);
	}
      } else if ("SetGradientPaint3".equals(cmd)) {
	System.out.println("DrawOptionListener: SetGradientPaint3");
	DrawAttr attr = view.getDrawAttr();
	if (attr != null) {
	  attr.setGradientColor1(Color.lightGray);
	  attr.setGradientColor2(Color.blue);
	  attr.setGradientMode(DrawAttr.LINEAR_GRADIENT_DIAGNAL_DOWN);
	}
      } else if ("SetGradientPaint4".equals(cmd)) {
	System.out.println("DrawOptionListener: SetGradientPaint4");
	DrawAttr attr = view.getDrawAttr();
	if (attr != null) {
	  attr.setGradientColor1(Color.lightGray);
	  attr.setGradientColor2(Color.blue);
	  attr.setGradientMode(DrawAttr.LINEAR_GRADIENT_DIAGNAL_UP);
	}
      }
    }
  }

}

class ToolButtonChangeListener extends DrawAction implements ChangeListener {

  public void stateChanged(ChangeEvent e) {
    if (e != null) {
      Object source = e.getSource();
      if (source instanceof JToggleButton) {
	JToggleButton button = (JToggleButton) source;
	/*
         * if (button.isSelected()) {
         * button.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLoweredBevelBorder(),
         * BorderFactory.createEmptyBorder(2,2,2,2))); } else {
         * button.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(),
         * BorderFactory.createEmptyBorder(2,2,2,2))); }
         */
      }
    }
  }

}

class UndoChangeListener extends DrawAction implements ChangeListener {

  UndoChangeListener(JMenuItem undoMenuItem, JMenuItem redoMenuItem) {
    this.undoMenuItem = undoMenuItem;
    this.redoMenuItem = redoMenuItem;
    if (undoMenuItem != null) {
      undoMenuItem.setEnabled(false);
    }
    if (redoMenuItem != null) {
      redoMenuItem.setEnabled(false);
    }
  }

  public void stateChanged(ChangeEvent e) {
    if (e != null) {
      Object source = e.getSource();
      if (source instanceof UndoManager) {
	UndoManager um = (UndoManager) source;
	if (undoMenuItem != null) {
	  undoMenuItem.setEnabled(um.hasUndoCommand());
	}
	if (redoMenuItem != null) {
	  redoMenuItem.setEnabled(um.hasRedoCommand());
	}
	main.setChanged(um.isChanged());
      }
    }
  }

  protected JMenuItem undoMenuItem, redoMenuItem;

}
